trigger PA_Insert_Percentage_Trigger on Productivity_Allocations__c (before insert, before update, after insert) {
    if(Trigger.isBefore)
    {
        if(Trigger.isInsert)
        {
            String errmsg = '';
            Boolean isError = false;
            
            Productivity_Allocations__c NewPA = Trigger.new[0];
            
            
            Decimal Percent3 = NewPA.Allocation_Percentage__c ;
                
                        
            Opportunity RelatedOp = [Select Id, Opportunity_Percentage_Allocated__c, OwnerId
                                from Opportunity
                                where Id =: NewPA.Opportunity_Name__c Limit 1]; 
                                Percent3 = Percent3 + RelatedOp.Opportunity_Percentage_Allocated__c;
                if (Percent3 > 100.00){
                    errmsg += 'Total Productivity Allocation percent is currently '+Percent3+'% The Total Allocation percentage cannot be greater than 100%';
                    isError = true;
                    NewPA.addError(errmsg);
                }
        
        }
        
        Map<ID, Set<ID>> salesAssociateForOppMap = new Map<ID, Set<ID>>();
        Set<ID> salesAssociateIDSet = new Set<ID>();
        Set<ID> opportunityIDSet = new Set<ID>();
        Map<ID, String> salesAssociateNameMap  = new Map<ID, String>();
        for(Productivity_Allocations__c pa:Trigger.new)
        {
            opportunityIDSet.add(pa.Opportunity_Name__c);
        }
        if(opportunityIDSet.size()> 0)
        {
            Map<ID, Opportunity> opportunityMap = new Map<ID, Opportunity>([select id,(select id, sales_associate__c, sales_associate__r.name from Productivity_Allocations__r) from Opportunity where id in :OpportunityIDSet]);
            for(Opportunity o: opportunityMap.values())
            {
                salesAssociateIDSet = new Set<ID>();
                for(Productivity_Allocations__c pa: o.Productivity_Allocations__r)
                {
                    salesAssociateIDSet.add(pa.Sales_Associate__c);
                    salesAssociateNameMap.put(pa.sales_associate__c, pa.sales_associate__r.name);
                    if(Trigger.oldMap != null && Trigger.oldMap.get(pa.id) != null && Trigger.oldMap.get(pa.id).sales_associate__c == Trigger.newMap.get(pa.id).sales_associate__c)
                    {
                        salesAssociateIDSet.remove(pa.sales_associate__c);
                        salesAssociateNameMap.remove(pa.sales_associate__c);
                    }
                }
                if(salesAssociateIDSet.size() > 0)
                    salesAssociateForOppMap.put(o.id, salesAssociateIDSet);
             }
      
            if(salesAssociateIDSet.size() > 0)
            {
                for(Productivity_Allocations__c pa:Trigger.new)
                {
                    if(salesAssociateForOppMap != null && pa != null && salesAssociateForOppMap.get(pa.opportunity_name__c) != null && salesAssociateForOppMap.get(pa.opportunity_name__c).contains(pa.sales_associate__c) == true)
                    {
                        pa.addError(salesAssociateNameMap.get(pa.Sales_Associate__c)+' is already assinged allocations for this particular opportunity. Please select another Sales person for this Productivity Allocations.');
                    }
                 }
             }
         }
    }
    
    if(Trigger.isAfter && Trigger.isInsert)
    {
        Map<ID, ID> paToOppMap = new Map<ID, ID>();
        Set<ID> oppSet = new Set<ID>();
        for(Productivity_Allocations__c pa: Trigger.new)
        {
            paToOppMap.put(pa.id, pa.opportunity_name__c);
            oppSet.add(pa.opportunity_name__c);
        }
        
        List<OpportunityLineItem> oliList = [select id, opportunityid, pricebookentry.product2.id, Added_Value__c, End__c, Flex__c, Description, ListPrice, make_good__c, servicedate, UnitPrice, quantity, start__c, TotalPrice from opportunitylineitem where opportunityid = :oppSet]; 
        List<reservations__c> reservationsList = new List<Reservations__c>();
        for(Productivity_Allocations__c pa: Trigger.new)
        {
            for(OpportunityLineItem oliNew: oliList)
            {
                if(pa.opportunity_name__c == oliNew.opportunityid)
                {
                    Reservations__c r = new reservations__c();
                    r.Added_Value__c = oliNew.Added_Value__c;
                    r.End__c = oliNew.End__c;
                    r.Start__c = oliNew.Start__c;
                    r.Make_good__c = oliNew.Make_good__c;
                    r.Flex__c = oliNew.Flex__c;
                    r.Line_Description__c = oliNew.Description;
                    r.List_Price__c= oliNew.ListPrice;
                    r.Opportunity_Product_Date__c = oliNew.servicedate;
                    r.Opportunity_Product_Sales_Price__c = oliNew.UnitPrice;
                    r.Quantity__c = oliNew.quantity;
                    r.Total_Price__c = oliNew.TotalPrice;    
                    r.opportunity_product__c = oliNew.pricebookentry.product2.id;
                    r.Related_Productivity_Allocation__c = pa.id;
                      
                    reservationsList.add(r);
                    if(reservationsList.size() == 1000)
                    {
                        insert reservationsList;
                        reservationsList.clear();
                    }
                }
            }
        }                    
        insert reservationsList;
    }    
}